import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

public class ServerMain {
    public static void main(String[] args) throws IOException {
        // ssc init
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // bind
        serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1", Global.port));
        // set non blocking
        serverSocketChannel.configureBlocking(false);
        // selector init
        Selector selector = Selector.open();
        // regist event
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // single thread
        while (true) {
            selector.select(1000);
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                try {
                    handleKey(selector, key);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void handleKey(Selector selector, SelectionKey key) throws IOException {
        if (key.isValid()) {
            if (key.isAcceptable()) {
                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                SocketChannel sc = ssc.accept();
                sc.configureBlocking(false);
                sc.register(selector, SelectionKey.OP_READ);
                System.out.println("server accepted client connect req.");
            }
            if (key.isReadable()) {
                SocketChannel channel = (SocketChannel) key.channel();
                String clientInfo = channel.getRemoteAddress().toString();
                // read
                ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                int count = channel.read(readBuffer);
                if (count > 0) {
                    readBuffer.flip();
                    byte[] bytes = new byte[readBuffer.remaining()];
                    readBuffer.get(bytes);
                    String recv = new String(bytes, "UTF-8");
                    System.out.println("server recv :" + recv + " " + clientInfo);
                    // write
                    String resp = null;
                    if (recv != null && recv.equals("query time order.")) {
                        resp = "replay:" + new Date();
                    } else {
                        resp = "err order";
                    }
                    byte[] respBytes = resp.getBytes();
                    ByteBuffer writeBuffer = ByteBuffer.allocate(respBytes.length);
                    writeBuffer.put(respBytes);
                    writeBuffer.flip();
                    channel.write(writeBuffer); // flush?
                } else if (count < 0) {
                    key.cancel();
                    channel.close();
                } else {
                    // skip 0. no read .no op
                }
            }
        }
    }
}
